<?php

if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}

class {{TableName}}Table extends WP_List_Table
{
    function __construct()
    {
        global $status, $page;
        parent::__construct(array(
            'singular' => '{{TableName}}',     //singular name of the listed records
            'plural' => '{{TableName}}',    //plural name of the listed records
            'ajax' => false        //does this table support ajax?
        ));

    }

    function column_default($item, $column_name)
    {
        switch ($column_name) {
            {% for col in columns %}
            {% if col.name in exclude_columns %}
            {% continue %}
            {% end %}
            case "{{col.name}}":
                return $item["{{col.name}}"];
            {% end %}
            default:
                return "";
        }
    }

    /** ************************************************************************
     * @see WP_List_Table::::single_row_columns()
     * @param array $item A singular item (one full row's worth of data)
     * @return string Text to be placed inside the column <td> (movie title only)
     **************************************************************************/
    function column_{{primary_key}}($item)
    {

        //Build row actions
        $actions = array(
            'edit' => sprintf('<a href="#" onclick="{{table_name}}_data_edit(%d);">Edit</a>', $item['{{primary_key}}']),
            'delete' => sprintf('<a href="#" onclick="{{table_name}}_data_delete(%d);">Delete</a>', $item['{{primary_key}}']),
        );

        //Return the title contents
        return sprintf('%1$s %2$s',
            /*$1%s*/
            $item['{{primary_key}}'],
            /*$2%s*/
            $this->row_actions($actions)
        );
    }


    /** ************************************************************************
     * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
     * is given special treatment when columns are processed. It ALWAYS needs to
     * have it's own method.
     *
     * @see WP_List_Table::::single_row_columns()
     * @param array $item A singular item (one full row's worth of data)
     * @return string Text to be placed inside the column <td> (movie title only)
     **************************************************************************/
    function column_cb($item)
    {
        return sprintf(
            '<input type="checkbox" name="%1$s[]" value="%2$s" />',
            /*$1%s*/
            "{{table_name}}_id_arr",
            /*$2%s*/
            $item['{{primary_key}}']
        );
    }


    /** ************************************************************************
     * REQUIRED! This method dictates the table's columns and titles. This should
     * return an array where the key is the column slug (and class) and the value
     * is the column's title text. If you need a checkbox for bulk actions, refer
     * to the $columns array below.
     *
     * The 'cb' column is treated differently than the rest. If including a checkbox
     * column in your table you must create a column_cb() method. If you don't need
     * bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
     *
     * @see WP_List_Table::::single_row_columns()
     * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
     **************************************************************************/
    function get_columns()
    {
        $columns = array(
            'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
            '{{primary_key}}' => '{{primary_key}}'
            {% for col in columns %}
            {% if (col.name in exclude_columns) or col.name == primary_key %}
            {% continue %}
            {% end %}
            ,'{{col.name}}' => '{{col.name}}'
            {% end %}

        );
        return $columns;
    }


    /** ************************************************************************
     * Optional. If you want one or more columns to be sortable (ASC/DESC toggle),
     * you will need to register it here. This should return an array where the
     * key is the column that needs to be sortable, and the value is db column to
     * sort by. Often, the key and value will be the same, but this is not always
     * the case (as the value is a column name from the database, not the list table).
     *
     * This method merely defines which columns should be sortable and makes them
     * clickable - it does not handle the actual sorting. You still need to detect
     * the ORDERBY and ORDER querystring variables within prepare_items() and sort
     * your data accordingly (usually by modifying your query).
     *
     * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
     **************************************************************************/
    function get_sortable_columns()
    {
        $sortable_columns = array(
            '{{primary_key}}' => array('{{primary_key}}', true)
            {% for col in columns %}
            {% if (col.name not in order_columns) or col.name == primary_key %}
            {% continue %}
            {% end %}
            ,'{{col.name}}' => array('{{col.name}}', true)
            {% end %}

        );
        return $sortable_columns;
    }


    /** ************************************************************************
     * Optional. If you need to include bulk actions in your list table, this is
     * the place to define them. Bulk actions are an associative array in the format
     * 'slug'=>'Visible Title'
     *
     * If this method returns an empty value, no bulk action will be rendered. If
     * you specify any bulk actions, the bulk actions box will be rendered with
     * the table automatically on display().
     *
     * Also note that list tables are not automatically wrapped in <form> elements,
     * so you will need to create those manually in order for bulk actions to function.
     *
     * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
     **************************************************************************/
    function get_bulk_actions()
    {
        $actions = array(
            'delete' => '删除'
        );
        return $actions;
    }


    /** ************************************************************************
     * Optional. You can handle your bulk actions anywhere or anyhow you prefer.
     * For this example package, we will handle it in the class to keep things
     * clean and organized.
     *
     * @see $this->prepare_items()
     **************************************************************************/
    function process_bulk_action()
    {

        //Detect when a bulk action is being triggered...
        if ('delete' === $this->current_action()) {
            ${{table_name}}_id_arr = $_GET["{{table_name}}_id_arr"];
            if (isset(${{table_name}}_id_arr)) {
                $sql = "
                    DELETE FROM {{table_name}} WHERE {{primary_key}}=%s
                ";
                global $wpdb;
                foreach (${{table_name}}_id_arr as $item) {
                    $int_v = intval($item);
                    $wpdb->query($wpdb->prepare($sql, $int_v));
                }
            }
        }
    }


    /** ************************************************************************
     * REQUIRED! This is where you prepare your data for display. This method will
     * usually be used to query the database, sort and filter the data, and generally
     * get it ready to be displayed. At a minimum, we should set $this->items and
     * $this->set_pagination_args(), although the following properties and methods
     * are frequently interacted with here...
     *
     * @global WPDB $wpdb
     * @uses $this->_column_headers
     * @uses $this->items
     * @uses $this->get_columns()
     * @uses $this->get_sortable_columns()
     * @uses $this->get_pagenum()
     * @uses $this->set_pagination_args()
     **************************************************************************/
    function prepare_items()
    {
        global $wpdb; //This is used only if making any database queries

        /**
         * First, lets decide how many records per page to show
         */
        $per_page = 25;


        /**
         * REQUIRED. Now we need to define our column headers. This includes a complete
         * array of columns to be displayed (slugs & titles), a list of columns
         * to keep hidden, and a list of columns that are sortable. Each of these
         * can be defined in another method (as we've done here) before being
         * used to build the value for our _column_headers property.
         */
        $columns = $this->get_columns();
        $hidden = array();
        if (!current_user_can("list_users")) {
        }
        $sortable = $this->get_sortable_columns();


        /**
         * REQUIRED. Finally, we build an array to be used by the class for column
         * headers. The $this->_column_headers property takes an array which contains
         * 3 other arrays. One for all columns, one for hidden columns, and one
         * for sortable columns.
         */
        $this->_column_headers = array($columns, $hidden, $sortable);


        /**
         * Optional. You can handle your bulk actions however you see fit. In this
         * case, we'll handle them within our package just to keep things clean.
         */
        $this->process_bulk_action();


        /**
         * This checks for sorting input and sorts the data in our array accordingly.
         *
         * In a real-world situation involving a database, you would probably want
         * to handle sorting by passing the 'orderby' and 'order' values directly
         * to a custom query. The returned data will be pre-sorted, and this array
         * sorting technique would be unnecessary.
         */
        function usort_reorder($a, $b)
        {
            $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : '{{primary_key}}'; //If no sort, default to primary_key
            $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; //If no order, default to asc
            $result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order
            return ($order === 'asc') ? $result : -$result; //Send final sort direction to usort
        }

        /**
         * REQUIRED for pagination. Let's figure out what page the user is currently
         * looking at. We'll need this later, so you should always include it in
         * your own package classes.
         */
        $current_page = $this->get_pagenum();

        /**
         * REQUIRED for pagination. Let's check how many items are in our data array.
         * In real-world use, this would be the total number of items in your database,
         * without filtering. We'll need this later, so you should always include it
         * in your own package classes.
         */
        $tb_name = "{{table_name}}";

        $count_sql = "
            SELECT
              COUNT(1) as total
            FROM $tb_name
        ";

        $total_items = $wpdb->get_var($count_sql);

        /**
         * The WP_List_Table class does not handle pagination for us, so we need
         * to ensure that the data is trimmed to only the current page. We can use
         * array_slice() to
         */

        $offset = ($current_page - 1) * $per_page;


        $data_sql = "
                SELECT
                  {{primary_key}}
                  {% for col in columns %}
                {% if (col.name in exclude_columns) or col.name==primary_key %}
                {% continue %}
                {% end %}
                  ,{{col.name}}
                {% end %}
                FROM $tb_name LIMIT %d, %d
            ";
        $data = $wpdb->get_results($wpdb->prepare($data_sql, array($offset, $per_page)), ARRAY_A);

        /**
         * REQUIRED. Now we can add our *sorted* data to the items property, where
         * it can be used by the rest of the class.
         */
        $this->items = $data;


        /**
         * REQUIRED. We also have to register our pagination options & calculations.
         */
        $this->set_pagination_args(array(
            'total_items' => $total_items,                  //WE have to calculate the total number of items
            'per_page' => $per_page,                     //WE have to determine how many items to show on a page
            'total_pages' => ceil($total_items / $per_page)   //WE have to calculate the total number of pages
        ));
    }
}

add_action('admin_menu', '{{table_name}}_table_list_menu_items');
add_action("admin_enqueue_scripts", "{{table_name}}_enqueue_scripts");
add_action('wp_ajax_{{table_name}}_data_save', '{{table_name}}_data_save_callback');
add_action('wp_ajax_{{table_name}}_data_get', '{{table_name}}_data_get_callback');
add_action('wp_ajax_{{table_name}}_data_delete', '{{table_name}}_data_delete_callback');
function {{table_name}}_data_save_callback(){
    $r = array("status" => 0, "data" => "", "act"=>0);
    global $wpdb;
    $data = array();
    {% for col in columns %}
    {% if (col.name in exclude_columns) or col.name == primary_key %}
    {% continue %}
    {% end %}
    $data["{{col.name}}"] = $_POST["{{col.name}}"];
    {% end %}
    if (empty($_POST["{{primary_key}}"])) {
        $wpdb->insert("{{table_name}}", $data);
        $id = $wpdb->insert_id;
        $r["status"] = 1;
        $r["data"] = $id;
    }else{
        $num = $wpdb->update("{{table_name}}", $data, array("{{primary_key}}"=>$_POST["{{primary_key}}"]));
        $r["status"] = 1;
        $r["data"] = $num;
		$r["act"] = 1;
    }
    die(json_encode($r));
}
function {{table_name}}_data_get_callback(){
	$r = array("status" => 0, "data" => "");
	$primary_key = $_POST["id"];
	global $wpdb;
	$sql = 'select
		{{primary_key}}
		{% for col in columns %}
		{% if col.name in exclude_columns %}
		{% continue %}
		{% end %}
		  ,{{col.name}}
		{% end %}
	from {{table_name}} where {{primary_key}}=%d';
	$row = $wpdb->get_row($wpdb->prepare($sql, $primary_key));
	$r["status"] = 1;
    $r["data"] = $row;
	die(json_encode($r));
}
function {{table_name}}_data_delete_callback(){
	$r = array("status" => 0, "data" => "");
	$primary_key = $_POST["id"];
	global $wpdb;
	$sql = "delete from {{table_name}} where {{primary_key}}=%d";
	$effects = $wpdb->query($wpdb->prepare($sql, $primary_key));
	$r["status"] = 1;
    $r["data"] = $effects;
	die(json_encode($r));
}
function {{table_name}}_enqueue_scripts(){
    $screen = get_current_screen();
    if ($screen->id=="toplevel_page_{{table_name}}_table_list_page"){
        wp_enqueue_script("jquery");
        wp_enqueue_script("jquery-ui-dialog");
        wp_enqueue_style("wp-jquery-ui-dialog");
    }

}
function {{table_name}}_table_list_menu_items()
{
    add_menu_page('{{TableName}}', '{{TableName}}', 'read', '{{table_name}}_table_list_page', '{{table_name}}_table_list_page', '', 15);
}
function {{table_name}}_table_list_page()
{
    //add_thickbox();
    //Create an instance of our package class...
    ${{table_name}}_list_table = new {{TableName}}Table();
    //Fetch, prepare, sort, and filter our data...
    ${{table_name}}_list_table->prepare_items();

    ?>
    <div class="wrap">
        <h2>{{TableName}}<a href="#" class="add-new-h2" onclick="{{table_name}}_dialog_form.dialog('open');">New</a></h2>
        <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
        <form id="orders-filter" method="get">
            <!-- For plugins, we also need to ensure that the form posts back to our current page -->
            <input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>"/>
            <!-- Now we can render the completed list table -->
            <?php ${{table_name}}_list_table->display() ?>
        </form>
    </div>
    <div id="{{table_name}}-dialog-form" title="Create {{TableName}}">
        <form id="{{table_name}}-data-form" method="post">
            {% for col in columns %}
            {% if (col.name in exclude_columns) or col.name == primary_key %}
            {% continue %}
            {% end %}
            {% set maxlength="" %}
            {% if col.length > 0 %}
            {% set maxlength='maxlength="'+'%s' % col.length+'"' %}
            {% end %}
            <label for="tb_{{col.name}}">{{col.name}}</label><input id="tb_{{col.name}}" name="{{col.name}}" type="{{col.data_type}}" {% raw maxlength %} class="form-field"/>
            {% end %}
            <input type="hidden" name="{{primary_key}}" id="tb_{{primary_key}}" class="form-field"/>
            <input type="hidden" name="action" value="{{table_name}}_data_save"/>
        </form>
    </div>
    <script type="text/javascript">
        var {{table_name}}_dialog_form = null;
        function {{table_name}}_data_edit(primary_key){
            {{table_name}}_dialog_form.dialog('open');
			var $ = jQuery;
			$("#{{table_name}}-data-form")[0].reset();
			$.post(ajaxurl, {"action":"{{table_name}}_data_get","id":primary_key}, function(rsp){
				$("#{{table_name}}-data-form .form-field").each(function () {
                var elem_name = $(this).attr("name");
					if (elem_name != undefined || elem_name != null || $.trim(elem_name) != "") {
						var remote_v = rsp.data[elem_name];
						var data_type = $(this).attr("type");
						if (data_type == "radio") {
							$('input[name="' + elem_name + '"]').each(function () {
								$(this).prop("checked", false);
								var v = $(this).val();
								if (v == remote_v) {
									$(this).prop("checked", true);
								}
							});
						} else if (data_type == "checkbox") {
							$(this).prop("checked", false);
							var v = $(this).val();
							if (v == remote_v) {
								$(this).prop("checked", true);
							}
						} else {
							$(this).val(remote_v);
						}
					}
				});
			}, "json");
        }
        function {{table_name}}_data_delete(primary_key){
            jQuery.post(ajaxurl, {"action":"{{table_name}}_data_delete","id":primary_key}, function(rsp){
				window.location.reload();
			}, "json");
        }
        jQuery(function ($) {
            {{table_name}}_dialog_form = $("#{{table_name}}-dialog-form").dialog({
                dialogClass: 'wp-dialog',
                autoOpen: false,
                height: 400,
                width: 350,
                modal: true,
                buttons: {
                    "Create an account": function () {
                        jQuery.post(ajaxurl, jQuery("#{{table_name}}-data-form").serialize(), function(rsp){
							if(rsp.status==1){
								if(rsp.act==0){
									$("#tb_{{primary_key}}").val(rsp.data);
								}
							}
                        }, "json");
                    },
                    Cancel: function() {
                        {{table_name}}_dialog_form.dialog( "close" );
						window.location.reload();
                    }
                },
                close: function() {
					window.location.reload();
                }
            });
        });
    </script>
    <?php
}